﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Solar.Security.Web;
using Solar.Security;
using System.Web.Security;
using Solar.Web.Utility;
using System.Configuration;
using Application.Service;

namespace Application.Website
{
    public class AuthenticationService : FormsAuthenticationServiceBase
    {
        public new const string AuthenticationType = "Website Authentication";
        public const string StaffAuthCookieName = "StaffAuthCookie";

        public AuthenticationService()
        {
            // TODO: apply configuration settings
            this.ExpirationTimeWindow = TimeSpan.FromDays(Double.Parse(ConfigurationManager.AppSettings["CookieTimeoutInDays"]));
            this.PersistsAuthentication = false;
            this.PersistsGuestSession = true;
        }

        protected bool PersistsGuestSession { get; set; }

        protected override IUserPrincipal GetUserCredential(string username, string password)
        {
            var service = new CustomerService();

            return service.Authenticate(username, password);
        }

        protected override void OnAuthenticated(IUserPrincipal user)
        {
            VisitContext.Session.Abandon(); // new life that is legal

            base.OnAuthenticated(user);
        }

        protected override void OnSignedOut(IUserPrincipal user)
        {
            VisitContext.Session.Abandon(); // new life that is wild

            base.OnSignedOut(user);
        }

        public static IUserPrincipal IdentifyVisitor()
        {
            var service = new CustomerService();

            var visitor = HttpContext.Current.User as IUserPrincipal;

            if (visitor == null || visitor == UserPrincipal.Unidentified
                || (!visitor.UserIdentity.IsAuthenticated && service.GetGuest(visitor.UserIdentity.Id) == null))
            {
                visitor = CreateGuestPrincipal();
            }

            return visitor;
        }

        //public static IUserPrincipal IdentifyStaff()
        //{
        //    var service = new AdminService();

        //    var staffAuth = HttpContext.Current.Request.Cookies[StaffAuthCookieName];

        //    if (staffAuth == null) // incorrect cookied identity
        //    {
        //        return UserPrincipal.Unidentified;
        //    }

        //    var staff = service.GetStaffPrincipal(staffAuth.Value);

        //    if (staff == null)
        //    {
        //        return UserPrincipal.Unidentified;
        //    }

        //    // persist authenticatication
        //    var cookie = new HttpCookie(StaffAuthCookieName, staffAuth.Value)
        //    {
        //        HttpOnly = true
        //    };
        //    HttpContext.Current.Response.Cookies.Add(cookie);

        //    return staff;
        //}

        public bool AuthenticateStaff(string id, string password)
        {
            var service = new AdminService();

            var staff = service.AuthenticateStaff(id, password);

            this.OnAuthenticating(staff);

            if (staff != null && staff.Identity.IsAuthenticated)
            {
                var cookie = new HttpCookie(StaffAuthCookieName, staff.UserIdentity.Name)
                {
                    HttpOnly = true
                };
                HttpContext.Current.Response.Cookies.Add(cookie);

                this.OnAuthenticated(staff);

                return true;
            }

            this.OnUnauthenticated(staff);

            return false;
        }

        public void SignOutStaff()
        {
            var cookies = HttpContext.Current.Response.Cookies;
            var removalCookie = new HttpCookie(StaffAuthCookieName, String.Empty)
            {
                Expires = DateTime.Now.AddYears(-50)
            };

            VisitContext.Session.Staff = null;

            cookies.Add(removalCookie);
        }

        private static IUserPrincipal CreateGuestPrincipal()
        {
            var service = new CustomerService();

            IUserPrincipal guest = null;

            // first, try client-side provided guest Id
            if (VisitContext.Cookie.GuestId.HasValue) // guest Id exists and is provided by client-side (browser)?
            {
                int guestId = VisitContext.Cookie.GuestId.Value;


                if (service.ValidateGuest(guestId)) // client-side provided guest Id is valid?
                {
                    guest = CreateGuestPrincipal(guestId);
                }
            }

            // if client does not provide guest Id or the provided guest Id is not valid, create one
            if (guest == null)
            {
                int guestId = service.AddGuest().Id;

                // create guest
                guest = CreateGuestPrincipal(guestId);
            }

            // persists client-side guest Id. If one has already existed, its timeout is reset
            VisitContext.Cookie.GuestId = guest.UserIdentity.Id;

            return guest;
        }

        private static IUserPrincipal CreateGuestPrincipal(int guestId)
        {
            IUserIdentity guestIdentity = new UserIdentity(guestId, String.Empty, String.Empty, String.Empty, false);

            IUserPrincipal guestPrincipal = new UserPrincipal(guestIdentity, new string[0]);

            return guestPrincipal;
        }
    }
}